package com.woniuxy.health.commodity.advice;

import com.woniuxy.health.commodity.annotation.Idempotent;
import com.woniuxy.health.commodity.constant.Constant;
import com.woniuxy.health.utils.TokenUtil;

import com.woniuxy.utils.result.Result;
import com.woniuxy.utils.result.ResultCodeEnum;
import com.woniuxy.utils.result.handle.WoniuHealthException;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

// 接口幂等性增强
@Component
@Aspect
public class InterfaceAdvice {

    private final RedisTemplate redisTemplate;

    public InterfaceAdvice(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Pointcut(value = "execution(* com.woniuxy.health.commodity.controller.*.*(..))")
    public void PointCut01(){}

    @Before(value = "PointCut01()")
    public void before(JoinPoint joinPoint){
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method =
                signature.getMethod();
        Idempotent annotation = method.getAnnotation(Idempotent.class);

        // 没有幂等注解就放行
        if (Objects.isNull(annotation)) return;
        // 获取请求对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        if (redisTemplate.hasKey(request.getRequestURI() + TokenUtil.getRequestIP(request))){
            throw new WoniuHealthException(ResultCodeEnum.HTTP_ALREADY_HANDLE);
        }

        // 通过请求方法名称和请求IP地址创建锁
        redisTemplate.opsForValue().setIfAbsent(request.getRequestURI() + TokenUtil.getRequestIP(request),
                "", 30, TimeUnit.SECONDS);
    }

}
